package com.divillysausages.dsair.dragdrop 
{
	import com.divillysausages.dsair.DSAir;
	import flash.desktop.ClipboardFormats;
	import flash.desktop.NativeDragManager;
	import flash.display.InteractiveObject;
	import flash.events.NativeDragEvent;
	
	/**
	 * The manager that controls the drag/dropping ability for the app. It lets us drag files from
	 * the desktop onto the app to load them
	 * @author Damian Connolly
	 */
	public class DragDropManager 
	{
		/********************************************************************/
		
		private static var m_instance:DragDropManager	= null;	// the only instance of this manager
		private static var m_creating:Boolean			= false;// are we creating this instance?
		
		/********************************************************************/
		
		/**
		 * The only instance of the DragDropManager for the app
		 */
		public static function get instance():DragDropManager
		{
			// create our instance
			if ( DragDropManager.m_instance == null )
			{
				DragDropManager.m_creating = true;
				DragDropManager.m_instance = new DragDropManager;
				DragDropManager.m_creating = false;
			}
			return DragDropManager.m_instance;
		}
		
		/********************************************************************/
		
		private var m_target:IDragDrop = null; // the target for the dragging and dropping
		
		/********************************************************************/
		
		/**
		 * Sets the target that will accept the drag and drop events/files
		 */
		public function set target( t:IDragDrop ):void
		{
			// remove event listeners from the old target if we have one
			if ( this.m_target != null )
			{
				this.m_target.removeEventListener( NativeDragEvent.NATIVE_DRAG_ENTER, this._onDragEnter );
				this.m_target.removeEventListener( NativeDragEvent.NATIVE_DRAG_EXIT, this._onDragExit );
				this.m_target.removeEventListener( NativeDragEvent.NATIVE_DRAG_DROP, this._onDragDrop );
			}
			
			// if it's null, just return
			if ( t == null )
				return;
			
			// make sure it's an interactive object
			if ( !( t is InteractiveObject ) )
			{
				DSAir.error( this, "The target passed to the DragDropManager (" + t + ") isn't an InteractiveObject" );
				return;
			}
			
			// hold it and add our listeners
			this.m_target = t;
			if ( this.m_target != null )
			{
				this.m_target.addEventListener( NativeDragEvent.NATIVE_DRAG_ENTER, this._onDragEnter );
				this.m_target.addEventListener( NativeDragEvent.NATIVE_DRAG_EXIT, this._onDragExit );
				this.m_target.addEventListener( NativeDragEvent.NATIVE_DRAG_DROP, this._onDragDrop );
			}
		}
		
		/********************************************************************/
		
		/**
		 * Creates the DragDropManager. As DragDropManager is a singleton, you should
		 * always use the instance getter instead of calling this directly
		 */
		public function DragDropManager() 
		{
			if ( !DragDropManager.m_creating )
				throw new Error( "DragDropManager is a singleton. Use the static instance getter" );
		}
		
		/********************************************************************/
		
		// called when we drag a file over our target
		private function _onDragEnter( e:NativeDragEvent ):void
		{
			// we only accept files
			if ( e.clipboard.hasFormat( ClipboardFormats.FILE_LIST_FORMAT ) )
			{
				NativeDragManager.acceptDragDrop( ( this.m_target as InteractiveObject ) );
				this.m_target.onDragOver();
			}
		}
		
		// called when we drag our file off our target
		private function _onDragExit( e:NativeDragEvent ):void
		{
			this.m_target.onDragOut();
		}
		
		// called when we drop our file over our target
		private function _onDragDrop( e:NativeDragEvent ):void
		{
			// get our files
			var files:Array = e.clipboard.getData( ClipboardFormats.FILE_LIST_FORMAT ) as Array;
			if ( files == null )
			{
				DSAir.warn( this, "The data on the clipboard wasn't an array of Files" );
				this.m_target.onDragOut();
				return;
			}
			
			// tell our target about the files
			this.m_target.onDragDrop( files );
		}
		
	}

}